package com.tools.web.filter.gateway;

import com.tools.common.object.Note;
import com.tools.common.thread.TimePair;
import com.tools.common.thread.Timeunit;
import com.tools.web.interceptor.auth.AuthenticationManager;

import java.util.Objects;

/**
 * 拉黑客户端 IP
 * 所需要的条件
 * 要开启该拉黑功能，需要满足所有条件。
 * */
@Note("拉黑客户端 IP 所需要的条件。" +
        "要开启该拉黑功能，需要满足所有条件。")
public class IPBlacksThreshold {

    @Note("缓存的 key 的前缀。【条件1】：不能为空")
    private String cacheKeyPrefix;

    @Note("在该时间内。【条件2】：大于 0")
    private TimePair thresholdTime;

    @Note("访问次数大于等于该阈值就拉黑。【条件3】：不能为 null")
    private int threshold;

    @Note("AuthenticationManager 是否启用的开关条件之一")
    private boolean useAuthHandler;

    @Note("身份拦截器 Interface 接口实例。不为 null 时启动。" +
            "该拦截器在启动后，在触发拉黑条件时，若该请求是携带了 token 的，" +
            "那么网关过滤器会在拉黑该用户的 IP 后，通过该实例调用对应的方法，封禁掉该用户的账户。")
    private AuthenticationManager authHandler;

    public IPBlacksThreshold() {}

    public IPBlacksThreshold(String cacheKeyPrefix, int threshold, long thresholdTime, Timeunit thresholdTimeunit) {
        this(cacheKeyPrefix, threshold, new TimePair(thresholdTime, thresholdTimeunit));
    }

    public IPBlacksThreshold(String cacheKeyPrefix, int threshold, TimePair thresholdTime) {
        this.setCacheKeyPrefix(cacheKeyPrefix);
        this.setThreshold(threshold);
        this.setThresholdTime(thresholdTime);
    }

    public String getCacheKeyPrefix() {
        return cacheKeyPrefix;
    }

    public void setCacheKeyPrefix(String cacheKeyPrefix) {
        this.cacheKeyPrefix = cacheKeyPrefix;
    }

    public int getThreshold() {
        return threshold;
    }

    public void setThreshold(int threshold) {
        this.threshold = threshold;
    }

    public TimePair getThresholdTime() {
        return thresholdTime;
    }

    public void setThresholdTime(TimePair thresholdTime) {
        this.thresholdTime = thresholdTime;
    }

    public boolean isUseAuthHandler() {
        return useAuthHandler;
    }

    public void setUseAuthHandler(boolean useAuthHandler) {
        this.useAuthHandler = useAuthHandler;
    }

    public AuthenticationManager getAuthHandler() {
        return authHandler;
    }

    public void setAuthHandler(AuthenticationManager authHandler) {
        this.authHandler = authHandler;
    }

    @Override
    public String toString() {
        return "IPBlacksThreshold{" +
                "cacheKeyPrefix='" + cacheKeyPrefix + '\'' +
                ", thresholdTime=" + thresholdTime +
                ", threshold=" + threshold +
                ", useAuthHandler=" + useAuthHandler +
                ", authHandler=" + authHandler +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        IPBlacksThreshold that = (IPBlacksThreshold) o;
        return Objects.equals(cacheKeyPrefix, that.cacheKeyPrefix);
    }

    @Override
    public int hashCode() {
        return Objects.hash(cacheKeyPrefix);
    }


    public IPBlacksThreshold cacheKeyPrefix(String cacheKeyPrefix) {
        this.setCacheKeyPrefix(cacheKeyPrefix);
        return this;
    }

    public IPBlacksThreshold threshold(int threshold) {
        this.setThreshold(threshold);
        return this;
    }

    public IPBlacksThreshold thresholdTime(TimePair thresholdTime) {
        this.setThresholdTime(thresholdTime);
        return this;
    }

    public IPBlacksThreshold useAuthHandler(boolean useAuthHandler) {
        this.setUseAuthHandler(useAuthHandler);
        return this;
    }

    public IPBlacksThreshold authHandler(AuthenticationManager authHandler) {
        this.setAuthHandler(authHandler);
        return this;
    }

    @Note("判断是否开启 【拉黑客户端 IP 的功能】")
    public boolean isEnabled() {
        return cacheKeyPrefix != null && !cacheKeyPrefix.isEmpty()
                && threshold > 0
                && thresholdTime != null;
    }

    @Note("是否开启了 【同步封禁用户账户的功能】")
    public boolean isEnabledDisabledUser() {
        return useAuthHandler && authHandler != null;
    }
}